package com.zhuss.core.auth;

import java.lang.reflect.Method;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Component;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.method.HandlerMethod;
import org.springframework.web.servlet.HandlerInterceptor;
import org.springframework.web.servlet.ModelAndView;

import com.zhuss.appconfig.TokenProcessor;
import com.zhuss.bean.bo.core.auth.CheckAuthBo;
import com.zhuss.common.Processor;
import com.zhuss.enums.EnumUtil;
import com.zhuss.enums.RequestMethod;
import com.zhuss.enums.SystemEnum;
import com.zhuss.exception.AabException;
import com.zhuss.exception.ExceptionCode;
import com.zhuss.util.HeaderUtil;

@Component
public class FeignAuthenticationInterceptor implements HandlerInterceptor {
	
	@Value("${server.servlet.context-path}")
	private String contextPath;
	
	@Autowired
	@Qualifier("authCheck")
	private Processor<Object, CheckAuthBo> authCheck;
	
	@Autowired
	private TokenProcessor tokenProcessor;
	
    @Override
    public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object object) throws Exception {
        
    	String token = request.getHeader("token");// 从 http 请求头中取出 token
        
        String abUrl = request.getRequestURL().toString();
        String realUrl = abUrl.substring(abUrl.indexOf(contextPath));
        
        if (realUrl.startsWith(contextPath + "/swagger")) {
        	return true;
        }
        
        // 如果不是映射到方法直接通过
        if (!(object instanceof HandlerMethod)) {
            return true;
        }
        
        Integer requestMethod = null;
        
        HandlerMethod handlerMethod = (HandlerMethod) object;
        Method method = handlerMethod.getMethod();
        RequestMapping clzAnno = method.getDeclaringClass().getAnnotation(RequestMapping.class);
        RequestMapping getMethodAnno = method.getAnnotation(RequestMapping.class);
        PostMapping postMethodAnno =  method.getAnnotation(PostMapping.class); 
        if (getMethodAnno instanceof RequestMapping) {
        	requestMethod = RequestMethod.GET.key();
        }
        if (getMethodAnno instanceof PostMapping) {
        	requestMethod = RequestMethod.POST.key();
        }
        String[] clzUrl = clzAnno.value();
        String[] methodUrl = getMethodAnno == null ? postMethodAnno.value() : getMethodAnno.value();
        String url = clzUrl[0] + methodUrl[0];
        Long userId = tokenProcessor.getUserId(token);
        if (url.startsWith("/hk/")) {
        	return true;
        }
        if (url.startsWith("/orign/")) {
        	return true;
        }
        if (url.startsWith("/select/")) {
        	return true;
        }
        if (url.equals("/login/register")) {
        	return true;
        }
        
        if (!"/login/login".equals(url) && !"/login/bind".equals(url) && !"/login/init".equals(url)
        		&& !"/login/getOpenId".equals(url)) {
        	if (token == null || userId == null) {
        		initControl(response);
        		throw new AabException(ExceptionCode.登录超时);
        	}
        }
        
        
        // 初始化所属系统、当前用户
        Integer system = initSystemAndUserId(userId);
        
        CheckAuthBo bo = new CheckAuthBo();
        bo.setUrl(contextPath + url);
        bo.setToken(token);
        bo.setConcurrentUserId(userId);
        bo.setConcurrentSystem(system);
        bo.setRequestMethod(requestMethod);
        bo.setRealUrl(realUrl);
        if ((Boolean)authCheck.process(bo)) {
        	return true;
        } else {
        	initControl(response);
        	throw new AabException(ExceptionCode.没有url访问权限);
        }
    }

    private void initControl(HttpServletResponse response) {
    	response.setHeader("Access-Control-Allow-Origin", "*");
    	response.setHeader("Access-Control-Allow-Methods", "GET,POST");
	}

	private Integer initSystemAndUserId(Long userId) throws AabException {
		Integer system = EnumUtil.containsValue(SystemEnum.class, contextPath.substring(1));
		HeaderUtil.systemTl.set(system);
        if (userId != null) {
        	HeaderUtil.userIdTl.set(userId);
        } else {
        	HeaderUtil.userIdTl.set(null);
        }
        return (int)system;
    	/*Class<? extends HttpServletRequest> requestClass = request.getClass();
        try {
	        Field request1 = requestClass.getDeclaredField("request");
	        request1.setAccessible(true);
	        Object o = request1.get(request);
	        Field coyoteRequest = o.getClass().getDeclaredField("coyoteRequest");
	        coyoteRequest.setAccessible(true);
	        Object o1 = coyoteRequest.get(o);
	        Field headers = o1.getClass().getDeclaredField("headers");
	        headers.setAccessible(true);
	        MimeHeaders o2 = (MimeHeaders)headers.get(o1);
	        
        } catch (Exception e) {
        	throw new AabException(ExceptionCode.header设置失败);
        }*/
		
	}

	@Override
    public void postHandle(HttpServletRequest httpServletRequest, HttpServletResponse httpServletResponse, Object o, ModelAndView modelAndView) throws Exception {
    }

    @Override
    public void afterCompletion(HttpServletRequest httpServletRequest, HttpServletResponse httpServletResponse, Object o, Exception e) throws Exception {
    }

}
